package org.roguelikedevelopment.dweller.j2me;

import javax.microedition.lcdui.Font;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;

import org.roguelikedevelopment.dweller.common.application.DwellerCanvas;
import org.roguelikedevelopment.dweller.common.game.GameHandler;
import org.roguelikedevelopment.dweller.common.ui.MenuUI;
import org.roguelikedevelopment.dweller.common.util.Direction;
import org.roguelikedevelopment.dweller.common.util.Position;
import org.roguelikedevelopment.dweller.common.util.logger.Logger;


public class DwellerJ2MECanvas extends GameCanvas implements DwellerCanvas {
	
	private Font font;	
	
	protected GameHandler game;

	public int CHARACTER_OFFSETY = 0;
	public int characterWidth;
	public int characterHeight;
	public int charactersPerRow;
	public int charactersPerColumn;

	/** Pixel position of the last pointer pressed event */
	private Position pointerPressed = new Position(0, 0);

	/** Pixel position of the last pointer released event */
	private Position pointerReleased = new Position(0, 0);

	/** Pixel position of the last pointer released event */
	private Position pointerDragged = new Position(0, 0);
	
	/** Time when the last pointer pressed was received */
	private long pointerPressedTimestamp;

	private DwellerJ2MEGraphics dwellergraphics;
	
	private boolean dragging = false;
	
	/**
	 * Creates a new DwellerCanvas
	 */
	public DwellerJ2MECanvas(GameHandler game) {
		super(false);
		Logger.debug("DwellerCanvas()");
		this.game = game;
		setFullScreenMode(true);
		
		font = Font.getFont(Font.FACE_PROPORTIONAL, Font.STYLE_PLAIN, Font.SIZE_SMALL);
		characterWidth = (font.charWidth('@') + font.charWidth('!')) / 2;
		characterHeight = font.getHeight() - 2;

		dwellergraphics = new DwellerJ2MEGraphics(this);
	}

	public void loadGraphics() {
		dwellergraphics.loadGraphics();
	}
	
	public void loadASCII() {
		dwellergraphics.loadASCII();
	}
	
	public void useNormalTiles() {
		dwellergraphics.useNormalTiles();
	}
	
	public void useLargeTiles() {
		dwellergraphics.useLargeTiles();
	}
	
	/**
	 * Gets the name of a key associated with a key code
	 * @param keyCode Key code to get name of
	 * @return The name of the key or "Unknown" 
	 */
	public String getKeyCodeName(int keyCode) {
		if(keyCode == -1) {
			return "";
		}
		String keyName = "Unknown";
		try {
			keyName = getKeyName(keyCode);
		}
		catch(Exception e) {
		}
		return keyName;
	}
	
	
	
	private final void initialize() {
		charactersPerRow = getWidth() / characterWidth;
		charactersPerColumn = getHeight() / characterHeight;
		MenuUI.setPageHeight(charactersPerColumn);
	}
	
	/**
	 * Gets the font used by the canvas
	 * @return
	 */
	public final Font getFont() {
		return font;
	}
	
	/**
	 * Called by the application framework if the canvas size is changed
	 */
	public final void sizeChanged(int width, int height) {
		super.sizeChanged(width, height);
		initialize();
		dwellergraphics.updateSize();
	}
	
	/**
	 * Called by the application framework when the screen needs to be redrawn
	 * Clears the screen and draws the active UI 
	 */
	public void paint(Graphics g) {
		dwellergraphics.setGraphics(g);
		g.setColor(0x000000);
		g.fillRect(0, 0, getWidth(), getHeight());
		g.setFont(font);	
		game.render(dwellergraphics);
	}
	
	public void pointerDragged(int x, int y) {
		dragging = true;
		int ydist = pointerDragged.y - y;
		int xdist = pointerDragged.x - x;
		
		if(Math.abs(ydist) < getCharacterHeight() && Math.abs(xdist) < getCharacterHeight()) {
			return;
		}
		
		game.pointerDragged(Direction.direction(pointerDragged.x, pointerDragged.y, x, y));

		pointerDragged.x = x;
		pointerDragged.y = y;
		repaint();
	}
	
	
	
	public void pointerPressed(int x, int y) {
		pointerPressedTimestamp = System.currentTimeMillis();
		pointerPressed.x = x;
		pointerPressed.y = y;
		pointerDragged.x = x;
		pointerDragged.y = y;
		game.pointerPressed(pointerPressed);
		repaint();
	}
	
	public void pointerReleased(int x, int y) {
		if(dragging) {
			dragging = false;
			return;
		}
		pointerReleased.x = x;
		pointerReleased.y = y;
		game.pointerReleased(pointerReleased, System.currentTimeMillis() - pointerPressedTimestamp);
		repaint();
	}
	
	
	/**
	 * Called by the application framework when a key is pressed
	 * The keycode is passed to the active UI for processing and a request for a screen
	 * redraw is made
	 * @param keyCode Code of the pressed key
	 */
	public void keyPressed(int keyCode) {
		game.keyPress(keyCode);
		repaint();
	}
	
	public void keyRepeated(int keyCode) {
		game.keyPress(keyCode);
		repaint();
	}

	public int getCharacterHeight() {
		return characterHeight;
	}

	public int getCharactersPerColumn() {
		return charactersPerColumn;
	}

	public int getCharactersPerRow() {
		return charactersPerRow;
	}

	public int getTileWidth() {
		return dwellergraphics.getTileWidth();
	}

	public int getTileHeight() {
		return dwellergraphics.getTileHeight();
	}
	
	public int getTilesPerRow() {
		return dwellergraphics.getTilesPerRow();
	}
	
	public int getTilesPerColumn() {
		return dwellergraphics.getTilesPerColumn();
	}

	public int substringWidth(String str, int offset, int len) {
		return font.substringWidth(str, offset, len);
	}
	
	public int stringWidth(String str) {
		return font.stringWidth(str);
	}

	public boolean isTouchEnabled() {
		return hasPointerEvents();
	}
}
